package com.sl.plugin.step.json;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Lists;
import com.sl.core.domain.dto.JsonMappingFieldDefine;
import com.sl.core.utils.JsonUtil;
import com.sl.core.engine.meta.impl.AbstractProcessCompDescriptor;
import com.sl.core.engine.meta.row.ProcessRowDescriptor;
import com.sl.core.engine.meta.valuemeta.ValueMetaObject;
import com.sl.core.engine.step.ProcessCompService;
import com.sl.core.engine.step.impl.AbstractProcessComp;
import org.noear.snack.ONode;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 *
 */
public class JsonAssignComp extends AbstractProcessComp<Map<String, Object>, Map<String, Object>> implements ProcessCompService {


    public JsonAssignComp(AbstractProcessCompDescriptor abstractProcessCompDescriptor) {
        super(abstractProcessCompDescriptor);
    }

    @Override
    public Map<String, Object> input(Map<String, Object> param) {

        //开始处理
        //获取JsonDefine
        List<Map<String, Object>> listMapAttr = meta.getListMapAttr("output.params");
        List<JsonMappingFieldDefine> inputFieldDefine = JsonUtil.toList(listMapAttr, JsonMappingFieldDefine.class);

        ONode oNode = ONode.loadObj(param);
        assign(oNode, inputFieldDefine);

        return oNode.toObject();
    }

    private void assign(ONode oNode, List<JsonMappingFieldDefine> inputFieldDefine) {

        if (CollUtil.isEmpty(inputFieldDefine)) {
            return;
        }

        for (JsonMappingFieldDefine jsonFieldDefine : inputFieldDefine) {
            String jsonPath = jsonFieldDefine.getJsonPath();
            String defaultValue = jsonFieldDefine.getDefaultValue();
//            String fieldType = jsonFieldDefine.getFieldType();
            String funcList = jsonFieldDefine.getFuncList();
            if (StrUtil.isNotBlank(defaultValue)) {
                Object value = defaultValue;
                if (StrUtil.contains(defaultValue, "$")) {
                    value = oNode.select(defaultValue).toObject();
                }
                value = buildValue(jsonFieldDefine, value);

                oNode.selectOrNew(jsonPath).val(value);

            }
            if (StrUtil.isNotBlank(funcList)) {
                List<String> split = StrUtil.split(funcList, ",");
                for (String s : split) {
                    Object o = invokeFunc(oNode.select(jsonPath).toObject(), s);
                    oNode.selectOrNew(jsonPath).val(o);
                }
            }
            List<JsonMappingFieldDefine> children = jsonFieldDefine.getChildren();
            assign(oNode, children);
        }
    }
    public Object invokeFunc(Object param ,String funcName){
        if(StrUtil.equals(funcName,BizFuncListEnum.TO_STR.getCode())){
              return   JsonUtil.toStr(param);
        }else if(StrUtil.equals(funcName,BizFuncListEnum.EMPTY_STR.getCode())){
            return   StrUtil.EMPTY;
        }else{
            return funcName;
        }
    }

    private Object buildValue(JsonMappingFieldDefine jsonFieldDefine, Object value) {
        Boolean isArrayFlag = jsonFieldDefine.getIsArrayFlag();
        String fieldType = jsonFieldDefine.getFieldType();
        if (ObjectUtil.isNull(value)) {
            return null;
        }
        //如果是数组，并且值不是数组
        if (BooleanUtil.isTrue(isArrayFlag)) {

            if (value instanceof String) {
                if (JsonUtil.isJsonStr(value.toString())) {
                    value = JSONUtil.parse(value);
                }
            }

            if (value instanceof Collection<?>) {
                return value;
            }
            return Lists.newArrayList(value);
        }
        if (StrUtil.toString(ProcessRowDescriptor.outFieldTypeTransfer(fieldType)).equals(ValueMetaObject.TYPE)) {
            if (value instanceof String) {
                if (JsonUtil.isJsonStr(value.toString())) {
                    value = JSONUtil.parse(value);
                }
            }
        }
        return value;
    }
}
